package com.blog.service.impl;


import cn.hutool.captcha.CaptchaUtil;
import cn.hutool.captcha.LineCaptcha;
import com.blog.VO.LoginTokenVO;
import com.blog.VO.UserInfo;
import com.blog.dto.*;
import com.blog.entity.Users;
import com.blog.mapper.UsersMapper;
import com.blog.service.UsersService;
import com.blog.utils.CaptchaGenerator;
import com.blog.utils.JwtTokenProvider;
import com.blog.utils.MailUtils;
import com.blog.utils.RedisUtils;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.*;

/**
* @author 电脑小白
* @description 针对表【users】的数据库操作Service实现
* @createDate 2025-06-27 16:45:57
*/
@Service
public class UsersServiceImpl implements UsersService {

    @Resource
    private UsersMapper usersMapper;
    @Resource
    private JwtTokenProvider jwtTokenProvider;
    @Resource
    private AuthenticationManager authenticationManager;
    @Resource
    private RedisUtils redisUtils;
    @Resource
    private MailUtils mailUtils;
    @Resource
    private CaptchaGenerator captchaGenerator;

    private final PasswordEncoder passwordEncoder;

    public UsersServiceImpl(PasswordEncoder passwordEncoder)
    {
        this.passwordEncoder = passwordEncoder;
    }


    @Override
    public Result login(LoginDTO loginDTO) {
        Authentication authentication = authenticationManager.authenticate(
                new UsernamePasswordAuthenticationToken(
                        loginDTO.getEmail(),
                        loginDTO.getPassword()
                )
        );
        Users user = usersMapper.findByEmail(loginDTO.getEmail());
        //短期token,15分钟
        String token = jwtTokenProvider.generateToken(
                authentication.getName(),
                (List<GrantedAuthority>) authentication.getAuthorities(),900000 // 从认证对象获取权限
        );
        redisUtils.set("shorttoken" + token,token,900000);
        //长期token，24小时
        String refreshToken = jwtTokenProvider.generateToken(
                authentication.getName(),
                (List<GrantedAuthority>) authentication.getAuthorities(),86400000 // 从认证对象获取权限
        );
        redisUtils.set("longtoken" + refreshToken,refreshToken,86400000);
        UserInfo userInfo = UserInfo.builder()
                .nickname(user.getNickname())
                .email(user.getEmail())
                .avatar(user.getAvatar())
                .build();
        LoginTokenVO loginTokenVO = LoginTokenVO.builder()
                .token(token)
                .refreshToken(refreshToken)
                .userInfo(userInfo)
                .build();
        return Result.ok(loginTokenVO);
    }

    @Override
    public Result register(RegisterDTO registerDTO) {
        String password = registerDTO.getPassword();
        String confirmPassword = registerDTO.getConfirmPassword();
        String emailcode = registerDTO.getEmailcode();
        String email = registerDTO.getEmail();
        String emailcodenum = (String)redisUtils.get("mailcapthca:" + email);
        Users user = usersMapper.findByEmail(registerDTO.getEmail());
        if(user != null) {
            return Result.fail(422,"用户已存在",null);
        }
        if(emailcodenum == null) {
            return Result.fail(403,"邮箱验证码已过期",null);
        }

        if(!emailcode.equals(emailcodenum)) {
            return Result.fail(422,"邮箱验证码不匹配",null);
        }

        if(!password.equals(confirmPassword)) {
            return Result.fail(422,"密码不一致",null);
        }

        Users users =Users.builder()
                .nickname(registerDTO.getNickname())
                .email(registerDTO.getEmail())
                .password(passwordEncoder.encode(password))
                .role(1)
                .avatar(null)
                .createTime(LocalDateTime.now())
                .build();
        usersMapper.insertuser(users);
        return Result.ok();
    }

    @Override
    public Result captchapicture() {
        LineCaptcha lineCaptcha = CaptchaUtil.createLineCaptcha(150, 70);
        lineCaptcha.createCode();
        String captchaId = UUID.randomUUID().toString();
        String code = lineCaptcha.getCode();
        code = code.toLowerCase();
        redisUtils.set(captchaId,code, 240);
        String imageBase64 = lineCaptcha.getImageBase64();
        Map<String,String> result = new HashMap<>();
        result.put("captchaId",captchaId);
        result.put("captchaImage",imageBase64);
        return Result.ok(result);
    }



    @Override
    public Result setemailcode(EmailDTO emaildto) {
        //先判断是否填写了图片验证码
        if(emaildto.getCaptchacode() == null || emaildto.getCaptchacode().isEmpty()) {
            return Result.fail(422,"请填写图片验证码",null);
        }

        String captchacode = (String)redisUtils.get(emaildto.getCaptchaId());

        if(captchacode == null) {
            return Result.fail(403,"请刷新图片验证码",null);
        }

        if(!captchacode.equals(emaildto.getCaptchacode().toLowerCase())) {
            return Result.fail(422,"图片验证码不匹配",null);
        }

        if(redisUtils.get("mailcapthca:" + emaildto.getEmail()) != null) {
            redisUtils.delete("mailcapthca:" + emaildto.getEmail());
        }
        String mailcaptcha = captchaGenerator.generateNumericCode();

        String content = buildVerificationEmailContent(mailcaptcha);
        redisUtils.set("mailcapthca:" + emaildto.getEmail(),mailcaptcha,600);
        mailUtils.sendEmail(emaildto.getEmail(),"邮箱验证码",content);
        //登录成功之后删除图片验证码,防止有人通过该数据攻击
        redisUtils.delete(emaildto.getCaptchaId());
        return Result.ok();
    }

    @Override
    public Result reset_password(ResetPasswordDTO resetPasswordDTO) {
        Users users = usersMapper.findByEmail(resetPasswordDTO.getEmail());
        if(users == null) {
            return Result.fail(422,"用户还未注册账号",null);
        }
        //先判断是否填写了图片验证码
        if(resetPasswordDTO.getCaptchacode() == null || resetPasswordDTO.getCaptchacode().isEmpty()) {
            return Result.fail(422,"请填写图片验证码",null);
        }

        String captchacode = (String)redisUtils.get(resetPasswordDTO.getCaptchaId());

        if(captchacode == null) {
            return Result.fail(403,"图片验证码已过期",null);
        }

        if(!captchacode.equals(resetPasswordDTO.getCaptchacode().toLowerCase())) {
            return Result.fail(422,"图片验证码不匹配",null);
        }
        String email = resetPasswordDTO.getEmail();
        String emailcode = (String)redisUtils.get("mailcapthca:" + email);
        if(emailcode == null) {
            return Result.fail(403,"邮箱验证码已过期",null);
        }
        if(!emailcode.equals(resetPasswordDTO.getEmailcode())) {
            return Result.fail(422,"邮箱验证码不匹配",null);
        }
        String encode = passwordEncoder.encode(resetPasswordDTO.getPassword());
        Map<String,String> params = new HashMap<>();
        params.put("password",resetPasswordDTO.getPassword());
        params.put("email",email);
        usersMapper.updatePassword(encode,email);
        return Result.ok();
    }

    @Override
    public Result refreshToken(String refreshToken) {
        //首先判断这个这个长期token是否有效
        if(redisUtils.get("longtoken" + refreshToken) == null) {
            return Result.fail(422,"用户已经登出,请重新登录",null);
        }
        if(!jwtTokenProvider.validateToken(refreshToken,2)) {
            String token = jwtTokenProvider.refreshToken(refreshToken);
            return Result.ok(token);
        }
        return Result.fail(422,"token已过期,请重新登录",null);
    }

    @Override
    public Result getUserInfo(String token) {
        if(!jwtTokenProvider.validateToken(token,1)) {
            String email = jwtTokenProvider.getEmailFromToken(token);
            Users user = usersMapper.findByEmail(email);
            UserInfo userInfo = UserInfo.builder()
                    .email(user.getEmail())
                    .nickname(user.getNickname())
                    .avatar(user.getAvatar())
                    .build();
            return Result.ok(userInfo);
        }
        return Result.fail(401,"无效的tokn", null);
    }

    private String buildVerificationEmailContent(String verificationCode) {
        return "<html>" +
                "<head><meta charset=\"UTF-8\"></head>" +
                "<body style=\"font-family: Arial, sans-serif;\">" +
                "<div style=\"max-width: 600px; margin: 0 auto; padding: 20px;\">" +
                "<h3 style=\"color: #333;\">亲爱的用户：</h3>" +
                "<p style=\"color: #555;\">您正在进行博客账号验证，验证码为：</p>" +
                "<div style=\"background-color: #f5f5f5; padding: 10px; text-align: center; font-size: 24px; font-weight: bold; margin: 20px 0;\">" +
                verificationCode +
                "</div>" +
                "<p style=\"color: #555;\">该验证码1分钟内有效，请及时完成验证。</p>" +
                "<p style=\"color: #555;\">如果您没有请求此验证码，请忽略此邮件。</p>" +
                "<p style=\"color: #888; font-size: 12px; margin-top: 30px;\">此为系统邮件，请勿回复</p>" +
                "</div>" +
                "</body>" +
                "</html>";
    }


}




